package com.ia.bo;

import com.ia.util.lectorEstaciones;
import com.ia.sd.Transbordo;

public class mapaMetro {

    private final int nLineas = 3;
    private final int nTrasbordos = 3;
    private final float costeMin = 0.5f;
    // nombre de las líneas: A, B, C
    private final char[] nombreLinea;
    // 0:nombre, 1:pos1, 2:pos2, 3:linea1, 4:linea2, 5:coste
    private String[][] trasbordos;
    // número de estaciones por línea
    private int[] nEstaciones;
    // nombre de las estaciones por línea
    private String[][] lineas;
    // valores de g y h
    private float[][] g;
    private float[][] h;
    
    private static mapaMetro mapaMetro = new mapaMetro();

    public static mapaMetro getMapaMetro() {
        if(mapaMetro==null){
            mapaMetro = new mapaMetro();
        }
        return mapaMetro;
    }
    
    private mapaMetro() {
        this.nombreLinea = new char[]{'A', 'B', 'C'};
        lectorEstaciones lector = new lectorEstaciones(this.nLineas, this.nTrasbordos);
        lector.leerEstaciones();
        loadData(lector);
        
    }
    
     private void loadData(lectorEstaciones lector){
        this.nEstaciones = lector.getnEstaciones();
        this.lineas=lector.getLineas();
        this.trasbordos=lector.getTrasbordos();
        this.g=lector.getG();
        this.h=lector.getH();
    }
     
    public float obtenerCosteTrasbordo(int pos, int linea) {
        int numT = 0, pos1 = 0, pos2 = 0, linea1 = 0, linea2 = 0;
        Transbordo t=new Transbordo();
        this.buscarTrasbordo(this.lineas[linea][pos], t);
        return t.getCoste();
    }
    
    // numT es la posición en el array de trasbordos
    public boolean buscarTrasbordo(String trasbordo, Transbordo t) {
        boolean respuesta = false;
        int i = 0;
        while (!(respuesta) && (i < trasbordos.length)) {
            if (trasbordos[i][0].equals(trasbordo)) {
                respuesta = true;                
                int numT = i;
                int pos1  = Integer.parseInt(trasbordos[i][1]);
                int pos2  = Integer.parseInt(trasbordos[i][2]);
                int linea1  = Integer.parseInt(trasbordos[i][3]);
                int linea2  = Integer.parseInt(trasbordos[i][4]);
                float coste  = Float.parseFloat(trasbordos[i][5]);
                t.setCoste(coste);
                t.setLinea1(linea1);
                t.setLinea2(linea2);
                t.setNumT(numT);
                t.setPos1(pos1);
                t.setPos2(pos2);
               
            }
            else i++;
        }
        return respuesta;
    }
    
    public int buscarTrasbordoMasCercano(int pos, int linea) {
        int i = 0, j = 0, respuesta;
        int[] posT = {0,0};
        while (j < 2) {
            if (Integer.parseInt(trasbordos[i][3]) == linea) {
                posT[j] = Integer.parseInt(trasbordos[i][1]);
                j++;
            } else if (Integer.parseInt(trasbordos[i][4]) == linea) {
                posT[j] = Integer.parseInt(trasbordos[i][2]);
                j++;
            } else i++;
        }
        respuesta = ((Math.abs(posT[0] - pos)) < (Math.abs(posT[1] - pos))) ? posT[0] : posT[1];
        return respuesta;
    }
    
    
    public float obtenerH(int posO, int posD, int lineaO, int lineaD) {
        
        float  h = 0f;
        Transbordo t=new Transbordo();
        if (this.buscarTrasbordo(lineas[lineaO][posO], t)) {
            int pos = posD;
            for(int i = 0; i < lineaD; i++) pos += this.nEstaciones[i];
            h = this.h[t.getNumT()][pos];
        } else {
            if (lineaO == lineaD) {
                h = (Math.abs(posO - posD)) * this.costeMin;
            } else {
                int posT = this.buscarTrasbordoMasCercano(posO, lineaO);
                h = (Math.abs(posT - posO)) * this.costeMin;                
                this.buscarTrasbordo(lineas[lineaO][posT],t);
                int pos = posD;
                for(int i = 0; i < lineaD; i++) pos += this.nEstaciones[i];
                h += this.h[t.getNumT()][pos];
            }
        }
        return h;
    }
  
    public int[][] obtenerAdyacentes(int pos, int linea) {
        int[][] estaciones;        
        Transbordo t=new Transbordo();
        if (this.buscarTrasbordo(lineas[linea][pos], t)) {
            estaciones = new int[4][2];
            estaciones[0][0] = t.getPos1() - 1;
            estaciones[0][1] = t.getLinea1();
            estaciones[1][0] = t.getPos1() + 1;
            estaciones[1][1] = t.getLinea1();
            estaciones[2][0] = t.getPos2() - 1;
            estaciones[2][1] = t.getLinea2();
            estaciones[3][0] = t.getPos2() + 1;
            estaciones[3][1] = t.getLinea2();
        } else {
            if (pos == 0) {
                estaciones = new int[1][2];
                estaciones[0][0] = pos + 1;
                estaciones[0][1] = linea;
            } else if (pos == this.nEstaciones[linea]-1) {
                estaciones = new int[1][2];
                estaciones[0][0] = pos - 1;
                estaciones[0][1] = linea;
            } else {
                estaciones = new int[2][2];
                estaciones[0][0] = pos - 1;
                estaciones[0][1] = linea;
                estaciones[1][0] = pos + 1;
                estaciones[1][1] = linea;
            }
        }
        return estaciones;
    }
    
    public boolean igual(int posO, int posD, int lineaO, int lineaD) {
        boolean respuesta = false;
        Transbordo t=new Transbordo();
        if (this.buscarTrasbordo(lineas[lineaO][posO], t)) {
            respuesta = (((t.getLinea1() == lineaD) && (t.getPos1() == posD)) || ((t.getLinea2() == lineaD) && (t.getPos2() == posD)));
        } else {
            respuesta = ((posO == posD) && (lineaO == lineaD));
        }
        return respuesta;
    }
    
    public int getNLineas() {
        return nLineas;
    }
    
    public int getNTrasbordos() {
        return nTrasbordos;
    }
    
    public float getCosteMin() {
        return costeMin;
    }
    
    public char[] getNombreLinea() {
        return nombreLinea;
    }
    
    public String[][] getTrasbordos() {
        return trasbordos;
    }
    
    public int[] getNEstaciones() {
        return nEstaciones;
    }
    
    public String[][] getLineas() {
        return lineas;
    }
    
    public float[][] getG() {
        return g;
    }
    
    public float[][] getH() {
        return h;
    }

}
